# ~*~ coding: utf-8 ~*~
from flask import request, views, render_template, jsonify
from sqlalchemy import func

from apps.common.utils import fill_date_to_timestamp, timestamp_obj_to_str, list2dict
from apps.common.mixin import CompatibleWithSelect2Mixin
from apps.common import response
from apps.extensions import db
from apps.perms.mixin import PermissionRequiredMixin, LoginRequiredMixin
from ..models import AdminUser, Asset
from ..forms import AdminUserCreateUpdateForm


__all__ = [
    'AdminUserListAPI', 'AdminUserListView', 'AdminUserCreateView', 'AdminUserUpdateView', 'AdminUserDeleteView'
]


class AdminUserListAPI(CompatibleWithSelect2Mixin, PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-adminuser-list'

    def get(self):
        create_time = request.args.get('create_time')
        start_time = end_time = None
        if create_time:
            start_time = fill_date_to_timestamp('start', create_time.split('~')[0])
            end_time = fill_date_to_timestamp('end', create_time.split('~')[1])

        filter_conditions = {
            'and': [
                ('create_time', 'gte', start_time),
                ('create_time', 'lte', end_time),
            ],
            'or': [
                ('name', 'like', request.args.get('search')),
            ],
        }

        # 排序
        sort = request.args.get('sort') or 'create_time'
        order = request.args.get('order') or 'desc'
        order_by_list = [(sort, order), ]

        # 分页
        offset = request.args.get('offset') or 0
        limit = request.args.get('limit') or 12

        # Compatible with select2
        if request.values.get('type') == 'select2':
            filter_conditions, order_by_list, offset, limit = self.select2_queryset()

        admin_users, count = AdminUser.get_queryset(filter_conditions=filter_conditions,
                                                    order_by_list=order_by_list,
                                                    offset=offset, limit=limit)
        # 获取关联资产的数量
        admin_user_ids = [admin_user.id for admin_user in admin_users]
        assets_count = db.session.query(AdminUser.id, func.count(Asset.id)). \
            outerjoin(Asset, AdminUser.id == Asset.admin_user_id).\
            filter(AdminUser.id.in_(admin_user_ids)). \
            group_by(AdminUser.id). \
            all()
        assets_count_dict = list2dict(assets_count)

        results = list()
        for admin_user in admin_users:
            results.append({
                'id': admin_user.id,
                'name': admin_user.name,
                'username': admin_user.username,
                'login_mode': admin_user.login_mode_display,
                'asset_count': assets_count_dict.get(admin_user.id),
                'create_time': timestamp_obj_to_str(admin_user.create_time),
            })

        resp = {
            "data": {
                "rows": results,
                "total": count
            }
        }
        return jsonify(resp)


class AdminUserListView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-adminuser-list'

    def get(self):
        return render_template('assets/adminuser_list.html')


class AdminUserUpdateView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-adminuser-update'

    def get(self, pk):
        instance = db.session.query(AdminUser).get(pk)
        content = {
            'id': instance.id,
            'name': instance.name,
            'username': instance.username,
            'password': instance.password or '',
            'private_key': instance.private_key or ''
        }
        return render_template('assets/adminuser_update.html', **content)

    def post(self, pk):
        form = AdminUserCreateUpdateForm(request.values)
        instance = db.session.query(AdminUser).get(pk)
        if form.validate():
            _clean_data = form.data
            if instance.name != _clean_data.get('name'):
                if db.session.query(AdminUser).filter_by(name=_clean_data.get('name')).count():
                    return response.params_error({
                        'field': 'name',
                        'message': '管理用户名称不能重复'
                    })

            name = _clean_data.get('name')
            username = _clean_data.get('username')
            password = _clean_data.get('password') or None
            private_key = _clean_data.get('private_key') or None

            public_key = instance.public_key
            if private_key and private_key != instance.private_key:
                private_key, public_key = form.gen_keys()

            instance.name = name
            instance.username = username
            if private_key and not password:
                instance.set_auth(password=None, private_key=private_key, public_key=public_key)
            if not private_key and password:
                instance.set_auth(password=password, private_key=None, public_key=None)
            if private_key and password:
                instance.set_auth(password=password, private_key=private_key, public_key=public_key)
            db.session.commit()
            return response.success()
        else:
            return response.params_error(form.get_error())


class AdminUserCreateView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-adminuser-create'

    def get(self):
        return render_template('assets/adminuser_create.html')

    def post(self):
        form = AdminUserCreateUpdateForm(request.values)
        if form.validate():
            _clean_data = form.data
            if db.session.query(AdminUser).filter_by(name=_clean_data.get('name')).count():
                return response.params_error({
                    'field': 'name',
                    'message': '管理用户名称不能重复'
                })

            private_key, public_key = form.gen_keys()
            password = _clean_data.get('password') or None
            admin_user = AdminUser()
            admin_user.name = _clean_data.get('name')
            admin_user.username = _clean_data.get('username')
            admin_user.set_auth(password=password, private_key=private_key, public_key=public_key)
            db.session.add(admin_user)
            db.session.commit()
            return response.success()
        else:
            return response.params_error(form.get_error())


class AdminUserDeleteView(PermissionRequiredMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'assets-adminuser-delete'

    def post(self, pk):
        instance = db.session.query(AdminUser).get(pk)
        instance.delete()
        return response.success()

